<template>
  <div class="config">
    <!--<div class="config-header">首页配置</div>-->
    <tabs :tabs="tabs" />
    <!-- 装修操作 -->
    <section class="config-operation">
      <!-- 组件 -->
      <div class="sliderleft">
        <el-scrollbar>
          <sliderassembly :pointer="pointer" />
        </el-scrollbar>
      </div>

      <!-- 手机 -->
      <div class="main-center">
        <el-scrollbar>
          <div class="phone">
            <section id="imageTofile" ref="imageTofile" class="phoneAll">
              <!-- 顶部 -->
              <div class="phone-top">
                <div class="phone-top__container">
                  <span class="text">欢迎来到xxx教育！</span>
                  <span class="mlauto text mr20">
                    <img src="@/assets/images/template/pc/icon6.png" />
                    学习中心
                  </span>
                  <span class="text mr20">
                    <img src="@/assets/images/template/pc/icon1.png" />
                    购物车
                  </span>
                  <span class="text mr20">
                    <img src="@/assets/images/template/pc/icon2.png" />
                    客服中心
                  </span>
                  <img
                    class="mr20"
                    src="@/assets/images/template/pc/icon7.png"
                  />
                  <img
                    class="mr20"
                    src="@/assets/images/template/pc/icon5.png"
                  />
                  <img
                    class="mr10"
                    src="@/assets/images/template/pc/icon3.png"
                  />
                  <span class="text">登录</span>
                  <span class="line"></span>
                  <span class="text">注册</span>
                  <img
                    class="new"
                    src="@/assets/images/template/pc/icon4.png"
                  />
                </div>
              </div>
              <!-- 主体内容 -->
              <section
                class="phone-container"
                @drop="drop($event)"
                @dragover="allowDrop($event)"
                @dragleave="dragleaves($event)"
              >
                <div :class="pointer.show ? 'pointer-events' : ''">
                  <!-- 动态组件 -->
                  <component
                    :is="item.component"
                    v-for="(item, i) in pageComponents"
                    :key="i"
                    :datas="item.setStyle"
                    class="componentsClass"
                    :class="item.active && deleShow ? 'active' : ''"
                    :data-type="item.type"
                    :is-droping="droping"
                    @click.native="activeComponent(item, i)"
                  >
                    <div
                      v-show="item.active && deleShow"
                      slot="deles"
                      class="deles"
                    >
                      <!-- 上移 -->
                      <div class="item" @click.stop="moveUp(i, item)">
                        <i class="el-icon-top"></i>
                      </div>
                      <!-- 下移 -->
                      <div class="item" @click.stop="moveDown(i, item)">
                        <i class="el-icon-bottom"></i>
                      </div>
                      <!-- 删除组件 -->
                      <div class="item"> <!--@click.stop="deleteObj(i)"-->
                        <el-popover
                          v-model="item.delVisible"
                          placement="left"
                          width="160"
                          trigger="click"
                        >
                          <p>确定删除吗？</p>
                          <div style="text-align: right; margin: 0">
                            <el-button size="mini" type="text" @click="item.delVisible = false">取消</el-button>
                            <el-button type="primary" size="mini" @click="deleteObj(i)">确定</el-button>
                          </div>
                          <i slot="reference" class="el-icon-close"></i>
                        </el-popover>
                      </div>
                    </div>
                  </component>
                </div>
              </section>
            </section>
          </div>
        </el-scrollbar>
      </div>

      <!-- 右侧工具栏 -->
      <div class="decorateAll">
        <!-- 页面设置 -->
        <transition name="decorateAnima">
          <el-scrollbar>
            <!-- 动态组件 -->
            <component :is="rightcom" :datas="currentproperties" />
          </el-scrollbar>
        </transition>
      </div>
    </section>
    <!-- 按钮集合 -->
    <section class="config-buttons">
      <!--<el-button plain @click="reloads">重置 </el-button>-->
      <el-button plain @click="realTimeView.show = true">预览</el-button>
      <el-button :disabled="confirmLoading" @click="submit">保存</el-button>
      <el-button type="primary" :disabled="confirmLoading" @click="submitPush">保存并发布</el-button>
    </section>
    <realTimeView
      :datas="realTimeView"
      :val="{
        component: pageComponents
      }"
    />
  </div>
</template>

<script>
import utils from '@/utils/index' // 方法类

// 组件数据
import componentProperties from '@/utils/pcComponentProperties'

// 左侧组件大全文件
import sliderassembly from './components/sliderassembly'

// 右侧组件大全文件
import realTimeView from './components/realTimeView'

/* 组件目录 START */
import placementarea from './components/componentscom/placementarea'
import navigation from './components/componentscom/navigation'
import banner from './components/componentscom/banner'
import advert from './components/componentscom/advert'
import intentCourse from './components/componentscom/intentCourse'
import course from './components/componentscom/course'
import teacher from './components/componentscom/teacher'
import topic from './components/componentscom/topic'
import featured from './components/componentscom/featured'
/* 组件目录 END */

/* 右侧组件目录 START */
import navigationStyle from './components/rightslider/navigationStyle'
import bannersStyle from './components/rightslider/bannersStyle'
import advertStyle from './components/rightslider/advertStyle'
import intentCourseStyle from './components/rightslider/intentCourseStyle'
import courseStyle from './components/rightslider/courseStyle'
import teacherStyle from './components/rightslider/teacherStyle'
import topicStyle from './components/rightslider/topicStyle'
import featuredStyle from './components/rightslider/featuredStyle'
import Tabs from '../tabs';
/* 右侧组件目录 END */
export default {
  name: 'Config',
  components: {
    Tabs,
    sliderassembly,
    realTimeView,
    placementarea,
    navigation,
    banner,
    advert,
    intentCourse,
    course,
    teacher,
    topic,
    featured,
    navigationStyle,
    bannersStyle,
    advertStyle,
    intentCourseStyle,
    courseStyle,
    teacherStyle,
    topicStyle,
    featuredStyle
  },
  inject: ['reload'],
  data() {
    return {
      tabs: [
        {
          title: '模板配置',
          uri: '/site/website/pc/template/' + this.$route.params.id + '/config',
          meta: {
            permission: 'site.template.pc.config'
          }
        }
      ],
      realTimeView: {
        show: false // 是否显示预览
      },
      deleShow: true, // 删除标签显示
      index: '', // 当前选中的index
      rightcom: '', // 右侧组件切换
      currentproperties: {}, // 当前属性
      pageComponents: [], // 页面组件
      offsetY: 0, // 记录上一次距离父元素高度
      pointer: { show: false }, // 穿透
      onlyHeaderNav: '1-1', // 顶部导航
      onlyOne: ['1-1', '1-9'], // 只能存在一个的组件(组件的type) '1-2', '1-3', '1-4', '1-6', '1-7'
      confirmLoading: false, // 提交中
      formData: {
        publish: 0 // 是否发布 1:是 0: 否
      }, // 提交的数据
      droping: false // 拖动状态 拖动中
    }
  },
  created() {
    this.loadTemplateData()
  },
  mounted() {
    this.$store.dispatch('setLoading', 0);
  },
  methods: {
    /**
     * 当将元素或文本选择拖动到有效放置目标（每几百毫秒）上时，会触发此事件
     *
     * @param {Object} event event对象
     */
    allowDrop(event) {
      this.droping = true
      // 阻止浏览器的默认事件
      event.preventDefault()

      /* 获取鼠标高度 */
      const eventoffset = event.offsetY

      /* 如果没有移动不触发事件减少损耗 */
      if (this.offsetY === eventoffset) return
      else this.offsetY = eventoffset

      /* 获取组件 */
      const childrenObject = event.target.children[0]

      // 一个以上的组件计算
      if (this.pageComponents.length) {
        /* 如果只有一个组件并且第一个是提示组件直接返回 */
        if (
          this.pageComponents.length === 1 &&
          this.pageComponents[0].type === 0
        ) {
          return
        }

        /* 如果鼠标的高度小于第一个的一半直接放到第一个 */
        if (eventoffset < childrenObject.children[0].clientHeight / 2) {
          /* 如果第一个是提示组件直接返回 */
          if (this.pageComponents[0].type === 0) return

          /* 删除提示组件 */
          this.pageComponents = this.pageComponents.filter(
            res => res.component !== 'placementarea'
          )

          /* 最后面添加提示组件 */
          this.pageComponents.unshift({
            component: 'placementarea',
            type: 0
          })

          return
        }

        /* 记录距离父元素高度 */
        const childOff = childrenObject.offsetTop

        /* 鼠标在所有组件下面 */
        if (
          eventoffset > childrenObject.clientHeight ||
          childrenObject.lastChild.offsetTop -
            childOff +
            childrenObject.lastChild.clientHeight / 2 <
            eventoffset
        ) {
          /* 最后一个组件是提示组件返回 */
          if (this.pageComponents[this.pageComponents.length - 1].type === 0) {
            return
          }

          /* 清除提示组件 */
          this.pageComponents = this.pageComponents.filter(
            res => res.component !== 'placementarea'
          )

          /* 最后一个不是提示组件添加 */
          this.pageComponents.push({
            component: 'placementarea',
            type: 0
          })

          return
        }

        const childrens = childrenObject.children

        /* 在两个组件中间，插入 */
        for (let i = 0, l = childrens.length; i < l; i++) {
          const childoffset = childrens[i].offsetTop - childOff

          if (childoffset + childrens[i].clientHeight / 2 > event.offsetY) {
            /* 如果是提示组件直接返回 */
            if (this.pageComponents[i].type === 0) break

            if (this.pageComponents[i - 1].type === 0) break

            /* 清除提示组件 */
            this.pageComponents = this.pageComponents.filter(
              res => res.component !== 'placementarea'
            )

            this.pageComponents.splice(i, 0, {
              component: 'placementarea',
              type: 0
            })
            break
          } else if (childoffset + childrens[i].clientHeight > event.offsetY) {
            if (this.pageComponents[i].type === 0) break

            if (
              !this.pageComponents[i + 1] ||
              this.pageComponents[i + 1].type === 0
            ) {
              break
            }

            this.pageComponents = this.pageComponents.filter(
              res => res.component !== 'placementarea'
            )

            this.pageComponents.splice(i, 0, {
              component: 'placementarea',
              type: 0
            })

            break
          }
        }
      } else {
        /* 一个组件都没有直接push */
        this.pageComponents.push({
          component: 'placementarea',
          type: 0
        })
      }
    },

    /**
     * 当在有效放置目标上放置元素或选择文本时触发此事件
     *
     * @param {Object} event event对象
     */
    drop(event) {
      this.droping = false
      /* 获取数据 */
      const data = utils.deepClone(
        componentProperties.get(event.dataTransfer.getData('componentName'))
      )

      /* 查询是否只能存在一个的组件且在第一个 */
      /* const someOne = this.pageComponents.some((item, index) => {
        return (
          item.component === 'placementarea' &&
          index === 0 &&
          this.onlyOne.includes(data.type)
        )
      }) */
      /* if (someOne) {
        this.$message.info('固定位置的组件(如: 底部导航、悬浮)不能放在第一个!')
        this.dragleaves()
        return
      } */

      /* 头部导航只能放在第一个 */
      const someNav = this.pageComponents.some((item, index) => {
        return (
          item.component === 'placementarea' &&
          index != 0 &&
          data.type == this.onlyHeaderNav
        )
      })
      if (someNav) {
        this.$message.info('顶部导航只能放在第一个')
        this.dragleaves()
        return
      }

      /* 第一个只能是顶部导航 */
      const hasTopNav = this.pageComponents.find(item => item.component === 'navigation');
      if (hasTopNav) {
        const someTop = this.pageComponents.some((item, index) => {
          return (
              item.component === 'placementarea' &&
              index === 0 &&
              data.type !== this.onlyHeaderNav
          )
        })

        if (someTop) {
          this.$message.info('第一个只能是顶部导航')
          this.dragleaves()
          return
        }
      }

      /* 查询是否只能存在一个的组件 */
      const someResult = this.pageComponents.some(item => {
        return (
          this.onlyOne.includes(item.type) &&
          item.component === event.dataTransfer.getData('componentName')
        )
      })

      if (someResult) {
        this.$message.info('当前组件只能添加一个')
        /* 删除提示组件 */
        this.dragleaves()
        return
      }

      /* 替换 */
      utils.forEach(this.pageComponents, (res, index) => {
        /* 修改选中 */
        if (res.active) res.active = false
        /* 替换提示 */
        this.index = index
        if (res.component === 'placementarea') {
          this.$set(this.pageComponents, index, data)
        }
      })

      /* 切换组件 */
      this.rightcom = data.style
      /* 丢样式 */
      this.currentproperties = data.setStyle

      // console.log(
      //   data,
      //   this.rightcom,
      //   this.currentproperties,
      //   '----------components data'
      // )
    },

    /**
     * 当拖动的元素或文本选择离开有效的放置目标时，会触发此事件
     *
     * @param {Object} event event对象
     */
    dragleaves() {
      this.droping = false
      /* 删除提示组件 */
      this.pageComponents = this.pageComponents.filter(
        res => res.component !== 'placementarea'
      )
    },

    /**
     * 选择组件
     *
     * @param {Object} res 当前组件对象
     */
    activeComponent(res, index) {
      this.index = index
      /* 切换组件 */
      this.rightcom = res.style
      /* 丢样式 */
      this.currentproperties = res.setStyle

      /* 替换 */
      utils.forEach(this.pageComponents, res => {
        /* 修改选中 */
        if (res.active === true) res.active = false
      })

      /* 选中样式 */
      res.active = true
    },

    /* 删除组件 */
    deleteObj(index) {
      this.pageComponents.splice(index, 1)
      if (this.pageComponents.length > 0) {
        this.index = index > 0 ? index - 1 : index
        this.activeComponent(this.pageComponents[this.index], this.index)
      } else {
        this.index = '' // 当前选中的index
        this.rightcom = '' // 右侧组件切换
        this.currentproperties = {} // 当前属性
      }
    },

    // 上移
    moveUp(index, row) {
      if (index > 0) {
        const upDate = this.pageComponents[index - 1]
        if (upDate.type == this.onlyHeaderNav) {
          this.$message.info('第一条是顶部导航，不可上移')
        } else {
          this.pageComponents.splice(index - 1, 1)
          this.pageComponents.splice(index, 0, upDate)
        }
      } else {
        this.$message.info('已经是第一条，不可上移')
      }
    },
    // 下移
    moveDown(index, row) {
      if (index + 1 === this.pageComponents.length) {
        this.$message.info('已经是最后一条，不可下移')
      } else {
        if (row.type == this.onlyHeaderNav) {
          this.$message.info('顶部导航只能放在顶部')
        } else {
          const downDate = this.pageComponents[index + 1]
          this.pageComponents.splice(index + 1, 1)
          this.pageComponents.splice(index, 0, downDate)
        }
      }
    },

    /* 页面刷新 */
    reloads() {
      this.$confirm('重置后您添加或者修改的数据将会失效, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.reload()
        })
        .catch(() => {})
    },
    loadTemplateData() {
      this.$http.get(
          '/admin/site/template/' + this.$route.params.id + '/data',
          {},
          ({ data }) => {
            const pageComponentsConfig = Array.isArray(data) ? data : []
            if (pageComponentsConfig.length > 0) {
              const pageComponents = []
              pageComponentsConfig.forEach(item => {
                const componentData = utils.deepClone(componentProperties.get(item.component))
                // 表单值覆盖
                componentData.setStyle.form = {
                  ...componentData.setStyle.form,
                  ...item.setStyle.form
                }
                pageComponents.push(componentData)
              })
              this.pageComponents = pageComponents
              this.activeComponent(this.pageComponents[0], 0)
            }
          },
          ({ msg }) => {
            this.$message.error(msg)
          }
      )
    },
    // 提交保存
    submit() {
      // // 将json转换成字符串
      // const data = JSON.stringify({
      //   component: JSON.stringify(this.pageComponents)
      // })
      this.confirmLoading = true
      const templateData = JSON.parse(JSON.stringify(this.pageComponents))
      templateData.forEach(item => {
        delete item.setStyle.mock_source
      })
      this.$http.post(
          '/admin/site/template/' + this.$route.params.id + '/save',
          {
            template_data: JSON.stringify(templateData),
            ...this.formData
          },
          ({ msg }) => {
            this.$message.success(msg)
            this.confirmLoading = false
          },
          ({ msg }) => {
            this.$message.error(msg)
            this.confirmLoading = false
          }
      )
    },
    // 保存并发布
    submitPush() {
      this.formData.publish = 1
      this.submit()
    }
  }
}
</script>

<style lang="scss" scoped>
.pointer-events {
  pointer-events: none;
}

.config {
  width: 100%;
  height: calc(100vh - 100px);
  position: relative;
  padding-right: 30px;
  background: #f7f7f7;

  .config-header {
    height: 40px;
    font-size: 14px;
    font-weight: 500;
    color: #5191ff;
    line-height: 40px;
    padding-left: 20px;
    border-bottom: 1px solid #ebeef5;
    background: #fff;
  }

  /* 操作主体 */
  .config-operation {
    width: 100%;
    height: calc(100% - 41px - 71px);
    display: flex;
    position: relative;

    // 左侧组件
    .sliderleft {
      width: 270px;
      height: 100%;
      background: #fff;
      position: absolute;
      left: 0;
      top: 0;
      .el-scrollbar {
        height: 100%;
      }
      ::v-deep.el-scrollbar__wrap {
        height: 100%;
      }
    }

    .main-center {
      height: calc(100% - 20px);
      left: 270px;
      right: 405px;
      top: 20px;
      bottom: 0;
      position: absolute;
      ::v-deep.el-scrollbar {
        height: 100%;
      }
      ::v-deep.el-scrollbar__wrap {
        height: 100%;
      }
      ::v-deep.el-scrollbar__view {
        height: 100%;
      }

      /* 手机 */
      .phone {
        background: #dcdfe6;
        border-radius: 16px;
        padding: 8px;
        width: 900px;
        margin: 0 auto;
        /* 手机样式 */
        .phoneAll {
          border-radius: 16px;
          position: relative;
          background: #fafafa;

          .phone-top {
            background: #f5f5f5;
            .phone-top__container {
              width: 834px;
              margin: 0 auto;
              height: 28px;
              display: flex;
              align-items: center;
              position: relative;
              .text {
                font-size: 8px;
                font-weight: 400;
                color: #606266;
                line-height: 11px;
              }
              .item {
                font-size: 8px;
                font-weight: 400;
                color: #606266;
                line-height: 11px;
              }
              .mlauto {
                margin-left: auto;
              }
              .mr20 {
                margin-right: 20px;
              }
              .mr10 {
                margin-right: 10px;
              }
              .line {
                width: 1px;
                height: 7px;
                background: #dcdfe6;
                margin: 0 3px;
              }
              .new {
                position: absolute;
                right: 37px;
                top: 24px;
                z-index: 99;
              }
            }
          }

          /* 主体内容 */
          .phone-container {
            min-height: 560px;
            box-sizing: border-box;
            cursor: pointer;
            position: relative;
            .componentsClass {
              border: 1px solid transparent;
              &:hover {
                border: 1px dashed #5191ff;
              }
              &.active {
                border: 1px solid #5191ff;
              }
            }
          }
        }
      }
    }

    /* 右侧工具栏 */
    .decorateAll {
      width: 405px;
      height: 100%;
      background: #fff;
      position: absolute;
      right: 0;
      top: 0;
      .el-scrollbar {
        height: 100%;
      }
      ::v-deep.el-scrollbar__wrap {
        height: 100%;
      }
    }

    /* 删除组件 */
    .deles {
      position: absolute;
      left: 102%;
      top: 50%;
      z-index: 999;
      transform: translateY(-50%);
      background: #ffffff;
      border-radius: 2px;
      border: 1px solid #e4e7ed;

      padding: 10px;
      .item {
        width: 18px;
        height: 18px;
        border: 1px solid #303133;
        font-size: 12px;
        color: #303133;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        &:hover {
          border-color: #5191ff;
          color: #5191ff;
        }
        & + .item {
          margin-top: 14px;
        }
      }
    }
  }

  /* 按钮集合 */
  .config-buttons {
    height: 70px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: #fff;
    border-top: 1px solid #ebeef5;
    /* 下拉 */
    .frop {
      padding-right: 15px;
      .el-button.el-button--primary.el-dropdown-selfdefine {
        background: #fff;
        color: #000;
        border: 1px solid #dcdee0;
      }
    }
    .el-button {
      font-size: 14px;
      padding: 0 16px;
      height: 30px;
      &.el-button--primary {
        background: #155bd4;
      }
      &.el-button--danger {
        background: red;
      }
    }
  }
}

/* 动画 */
.decorateAnima-enter-active {
  transition: all 1.5s ease;
}
.decorateAnima-leave-active {
  transition: all 1.5s ease;
}
.decorateAnima-enter {
  transform: translate(8px, 8px);
  opacity: 0;
}
.decorateAnima-leave-to {
  transform: translate(8px, 8px);
  opacity: 0;
}

::v-deep .tab-wrapper{
  width: 100%!important;
}
::v-deep .page-tabs{
  height: 40px;
}
</style>
